package com.boot.proofing.common.db;/**
 * @description
 * @autor xbwu on 2018/5/14.
 */

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
import lombok.Getter;
import lombok.Setter;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.util.ArrayList;
import java.util.List;

/**
 * mybatis-plus 配置
 * @author xbwu
 * @create 2018-05-14 
 **/
@Configuration
@MapperScan({"com.boot.proofing.mpweb.**.mapper*"
    ,"com.gitee.sunchenbin.mybatis.actable.dao.*"})
public class MybatisPlusConfig {

    /**
     * mybatis自动建表插件模式
     * none：不启用
     * update:更新表结构
     * create:删除所有表，重新建表
     */
    @Value("#{configProperties['mybatis.table.auto']}")
    @Getter
    @Setter
    public String mybatisTableAuto;

    /**
     * mybatis-plus SQL执行效率插件
     * 设置  test 环境时开启
     */
    @Bean
    @Profile({"test"})
    public PerformanceInterceptor performanceInterceptor() {
        return new PerformanceInterceptor();
    }

    /**
     * 非mybatis-plus 自动建表更新表结构插件所需
     * @return
     * @throws Exception
     */
    @Bean
    public PropertiesFactoryBean configProperties() throws Exception{
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        propertiesFactoryBean.setLocations(resolver.getResources("classpath:config/baseConstant.properties"));
        return propertiesFactoryBean;
    }
    /**
     * 乐观锁机制激活
     * @return
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }


    /**
     * mybatis-plus分页插件<br>
     * 文档：http://mp.baomidou.com<br>
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        /*
         * 【测试多租户】 SQL 解析处理拦截器<br>
         * 这里固定写成租户 1 实际情况你可以从cookie读取，因此数据看不到tenant_id=1 以外的数据 <br>
         */
        List<ISqlParser> sqlParserList = new ArrayList<>();
        TenantSqlParser tenantSqlParser = new TenantSqlParser();
        //开启全局租户配置
        tenantSqlParser.setTenantHandler(new TenantHandler() {
            //租户拦截，全局过滤租户id为1的数据
            @Override
            public Expression getTenantId() {
                return new LongValue(1L);
            }

            @Override
            public String getTenantIdColumn() {
                return "tenant_id";
            }

            @Override
            public boolean doTableFilter(String tableName) {
                // 这里可以判断是否过滤表，或者指定sql方法@SqlParser(filter = true) 注解等效，也可以过滤
                //直接过滤自动建表时查询的数据库表结构
                if ("tables".equals(tableName)
                        ||"columns".equals(tableName)) {
                    return true;
                }
                return false;
            }
        });
        //加入全局租户拦截
        sqlParserList.add(tenantSqlParser);
        // 攻击 SQL 阻断解析器、加入解析链
        sqlParserList.add(new BlockAttackSqlParser());
        paginationInterceptor.setSqlParserList(sqlParserList);
        return paginationInterceptor;
    }

    /**
     * 全局更新插入拦截器
     * @return
     */
    @Bean
    public MetaObjectHandler metaObjectHandler(){
        return new MyMetaObjectHandler();
    }

    /**
     * 注入主键生成器
     */
    @Bean
    public IKeyGenerator keyGenerator(){
        return new H2KeyGenerator();
    }

    /**
     * 注入sql注入器
     */
    @Bean
    public ISqlInjector sqlInjector(){
        return new LogicSqlInjector();
    }

}
